﻿#ifndef APPMESSAGE_HPP
#define APPMESSAGE_HPP

#include <string>
#include <vector>
#include "common.h"

namespace mv {
class app_message {
public:
	app_message(const std::string& host, const int32_t& port, const std::vector<uint8_t>& data) {
		this->host_ = host;
		this->port_ = port;
		this->data_ = data;
	}
	app_message(const app_message& r) {
		this->host_ = r.host_;
		this->port_ = r.port_;
		this->data_ = r.data_;
	}
	app_message(app_message&& r) noexcept {
		this->host_ = std::move(r.host_);
		this->port_ = r.port_;
		this->data_ = std::move(r.data_);
	}
	app_message& operator =(const app_message& r) {
		if (this == &r) {
			return *this;
		}
		this->host_ = r.host_;
		this->port_ = r.port_;
		this->data_ = r.data_;
		return *this;
	}
	app_message& operator =(app_message&& r) noexcept {
		if (this == &r) {
			return *this;
		}
		this->host_ = std::move(r.host_);
		this->port_ = r.port_;
		this->data_ = std::move(r.data_);
		return *this;
	}
	bool is_empty() {
		return this->data_.empty();
	}
	int32_t get_cmd() {
		uint8_t b = this->data_[4];
		return (b & 0xff);
	}
	int32_t get_body_length() {
		uint8_t h = this->data_[2];
		uint8_t l = this->data_[3];
		short len = (h << 8 | l);
		return (len & 0xffff);
	}
	int32_t get_content_length() {
		return this->get_body_length() - 3; // CMD1+CRC2
	}
	std::vector<uint8_t> get_data() {
		return this->data_;
	}
	std::vector<uint8_t> get_content() {
		int32_t length = this->get_content_length();
		std::vector<uint8_t> buffer(length);
		memcpy(&buffer[0], &this->data_[5], length);

		return buffer;
	}
	std::string GetHost() {
		return this->host_;
	}
	int32_t get_port() {
		return this->port_;
	}
	bool check_format() {
		if (this->host_.empty() || this->data_.size() < 7){ // 头2+长度2+CMD1+CRC2
			return false;
		}
		int bodylen = this->get_body_length();
		if (this->data_.size() != bodylen + 4) { // 长度不对
			return false;
		}
		int cmd = this->get_cmd();
		if (cmd != CMD_HEARTBEAT
			&& cmd != CMD_LOGIN
			&& cmd != CMD_SERVER_MESSAGE
			&& cmd != CMD_CLIENT_MESSAGE) { // 未知cmd
			return false;
		}
		int dataLen = this->get_content_length();
		if (cmd == CMD_HEARTBEAT && dataLen != 0) {
			return false;
		}
		if (cmd == CMD_LOGIN && dataLen < 1) {
			return false;
		}
		if (cmd == CMD_SERVER_MESSAGE && dataLen < 1) { // 服务器消息必须有消息内容
			return false;
		}
		if (cmd == CMD_CLIENT_MESSAGE && dataLen > 0) { // 服务器确认消息无内容
			return false;
		}

		return true;
	}
private:
	std::string host_;
	int32_t port_;
	std::vector<uint8_t> data_;
};
} // namespace mv
#endif // APPMESSAGE_HPP